// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: xguo

#include "coin2/exchange/base/api_util/auth_key.h"

#include <experimental/filesystem>
#include <string>

#include <glog/logging.h>
#include <rapidjson/document.h>
#include <rapidjson/error/en.h>
#include <rapidjson/istreamwrapper.h>

using namespace std::string_literals;

const std::optional<std::string> AuthKey::GetValue(const char* key) const {
  if (document_.HasMember(key)) {
    return document_[key].GetString();
  }
  return {};
}

AuthKey AuthKey::FromDocument(const rapidjson::Document& document) {
  AuthKey ret;

  // owner
  if (document.HasMember("owner")) {
    ret.set_owner(document["owner"].GetString());
  } else if (document.HasMember("account_name")) {
    ret.set_owner(document["account_name"].GetString());
  }

  // key name
  if (document.HasMember("name")) {
    ret.set_key_name(document["name"].GetString());
  } else if (document.HasMember("key_name")) {
    ret.set_key_name(document["key_name"].GetString());
  }

  // access key
  if (document.HasMember("access_key")) {
    ret.set_access_key(document["access_key"].GetString());
  } else if (document.HasMember("api_key")) {
    ret.set_access_key(document["api_key"].GetString());
  }

  // secret key
  if (document.HasMember("secret_key")) {
    ret.set_secret_key(document["secret_key"].GetString());
  } else if (document.HasMember("api_secret")) {
    ret.set_secret_key(document["api_secret"].GetString());
  }

  // key name
  if (document.HasMember("generated")) {
    ret.set_generated(document["generated"].GetString());
  }

  // key name
  if (document.HasMember("generated_human")) {
    ret.set_generated_human(document["generated_human"].GetString());
  }

  // email
  if (document.HasMember("email")) {
    ret.set_email(document["email"].GetString());
  }

  // password
  if (document.HasMember("password")) {
    ret.set_password(document["password"].GetString());
  }

  // token
  if (document.HasMember("token")) {
    ret.set_token(document["token"].GetString());
  }

  // account_type
  if (document.HasMember("account_type")) {
    ret.set_account_type(document["account_type"].GetString());
  }

  // copy document due to other fields (like 'passphrase')
  ret.document_.CopyFrom(document, ret.document_.GetAllocator());

  return ret;
}

AuthKey AuthKey::FromFile(const std::string& filepath) {
  if (!std::experimental::filesystem::exists(filepath)) {
    throw std::runtime_error("\"" + filepath + "\" missing file.");
  }
  std::ifstream ifs(filepath.c_str());
  rapidjson::IStreamWrapper isw(ifs);
  rapidjson::Document document;
  document.ParseStream(isw);
  if (document.HasParseError()) {
    throw std::runtime_error("Parse Error. "s + GetParseError_En(document.GetParseError()));
  }
  return AuthKey::FromDocument(document);
}
